#pragma once

#include <vector>
#include <iostream>
#include "Sem.hpp"

const static int g_cap = 5;
using namespace SemRingModule;
template <class T>
class RingQueue
{
public:
    RingQueue(int cap = g_cap) : _cap(cap),
                                 _queue(cap),
                                 _sem_blank(cap), // 初始值为cap
                                 _sem_data(0),     // 初始值为0
                                 P_step(0),
                                 C_step(0)
    {
    }
    void Equeue(const T &item)
    {
        // 入队逻辑
        // 1 申请信号量 ，空位置信号量
        _sem_blank.P();
        // 2 放数据
        _queue[P_step] = item;
        P_step = (P_step + 1) % _cap;
        // 3 释放数据位置的信号量
        _sem_data.V();
    }

    void Pop(T *item)
    {
        // 出队逻辑
        // 1 申请数据位置的信号量
        _sem_data.P();
        // 2 取数据
        *item = _queue[C_step];
        C_step = (C_step + 1) % _cap;
        // 3 释放空位置信号量
        _sem_blank.V();
    }

private:
    std::vector<T> _queue;
    size_t _cap = 0;

    // 生产者
    SemRing _sem_blank; // 表示空位的信号量
    int P_step;
    // 消费者
    SemRing _sem_data; // 表示数据的信号量
    int C_step;
};